package vnc.ui;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;

import vnc.JDPacketAnalyzerLoader;
import vnc.analyzer.JDPacketAnalyzer;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;

public class PacketDetails extends JLayeredPane{
	
	IP4bit ipbit;
	UDPbit udpbit;
	Ethernetbit ebit;
	
	public Packet packet = null;
	List<JDPacketAnalyzer> analyzers;
	
	public List<JButton> layerButtons;
	
	public JScrollPane jspPacket;
	public JLabel jlPacket;
	
	int buttonLocationX;
	int buttonLocationY;
	int buttonSizeWidth;
	int buttonSizeHeight;
	
	private ImageIcon getImageIcon(final String path){
		return new ImageIcon(this.getClass().getResource(path));
	}
	
	private ImageIcon scaleImageIcon(ImageIcon icon, final int width, final int height){
		Image img = icon.getImage();
		
		Image newimg = img.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH);
		
		icon = new ImageIcon(newimg);

		return icon;
	}
	
	private void removeBoxBorder(JButton box){
		box.setBorderPainted(false);
		box.setContentAreaFilled(false);
		box.setDefaultCapable(false);
		box.setFocusPainted(false);
	}
	
	public void setPacket(Packet packet){
		this.packet = packet;
	}
	
	void analyzePacket(final Packet packet){
		
		layerButtons.clear();		
		this.removeAll();
		JButton jb;
		
		for(final JDPacketAnalyzer analyzer:analyzers){
			if(analyzer.isAnalyzable(packet)){
				analyzer.analyze(packet);

				jb = new JButton(scaleImageIcon(getImageIcon("/packet_images/"+ analyzer.getProtocolName() +"_L0.png"), buttonSizeWidth, buttonSizeHeight));
				jb.setRolloverIcon(scaleImageIcon(getImageIcon("/packet_images/"+ analyzer.getProtocolName() +"_L0.png"), buttonSizeWidth, buttonSizeHeight));
				removeBoxBorder(jb);
				
				jb.addMouseListener(new MouseAdapter(){
					public void mouseClicked(MouseEvent e){
						
								String[] names=analyzer.getValueNames();
								Object[] values=analyzer.getValues();
								if(analyzer.getProtocolName().equals("IPv4"))
									{
										bitDetailDisable();
										ipbit.getInfos(names,values,analyzer.getHeaderLength());
										ipbit.setVisible(true);
										
									}
								else if(analyzer.getProtocolName().equals("UDP"))
								{
									bitDetailDisable();
									udpbit.getInfos(names,values);
									udpbit.setVisible(true);
								
								}
								else if(analyzer.getProtocolName().equals("Ethernet"))
								{
									bitDetailDisable();
									ebit.getInfos(names,values);
									ebit.setVisible(true);
									
									
								}
							
							}
					});
				
				layerButtons.add(jb);
			}
		}
		
		for(int i=0; i<layerButtons.size(); i++){
			this.add(layerButtons.get(i), new Integer(2), 0);
			layerButtons.get(i).setBounds(buttonLocationX + (buttonSizeWidth*i), buttonLocationY, buttonSizeWidth, buttonSizeHeight);
		}
		
	}
	
	void showPacket(Packet p){
		
		byte[] bytesHeader=new byte[p.header.length];
	
		System.arraycopy(p.header,0,bytesHeader,0,p.header.length);
		
		StringBuffer buf=new StringBuffer();
		
		int k = 0; // for new line
		int z = 0; // just for printing
		
		for(JDPacketAnalyzer analyzer:analyzers){
			if(analyzer.isAnalyzable(packet)){
				analyzer.analyze(packet);
				
				for(int i=z; (z-i)<analyzer.getHeaderLength();z++){
					
					String d=Integer.toHexString((int)(bytesHeader[z]&0xff));
					
					if(i==z){
						k++;
						buf.append("<Font"+ analyzer.getProtocoloColorHtmlFontStyle() +">" + (d.length()==1?"0"+d:d)+" ");
					}else if((z-i)==(analyzer.getHeaderLength()-1)){
						k++;
						buf.append((d.length()==1?"0"+d:d)+ "</Font>" +" ");
					}else{
						k++;
						buf.append((d.length()==1?"0"+d:d)+" ");
					}
					if(k == 14){
						k = 0;
						buf.append("<br>");
					}
						
				}
				
			}
		}
		buf.append("<br>");
		
		byte[] bytesData=new byte[p.data.length];
		
		System.arraycopy(p.data,0,bytesData,0,p.data.length);
		
		for(int i=0,j;i<bytesData.length;){
			
			for(j=0;j<10 && i<bytesData.length;j++,i++){
				String d=Integer.toHexString((int)(bytesData[i]&0xff));
				buf.append((d.length()==1?"0"+d:d)+" ");
			 if(bytesData[i]<32 || bytesData[i]>126) bytesData[i]=46;
			}
			
			buf.append("["+new String(bytesData,i-j,j)+"]<br>");
		}
		
		jlPacket.setText("<html>" + buf.toString() + "</html>");
		
		this.add(jspPacket, new Integer(2), 0);
	}
	
	

	public void init(){
		
		if(packet != null){
			analyzePacket(packet);
			showPacket(packet);
			repaint();
		}
		
		udpbit = new UDPbit();
		udpbit.setBounds(buttonLocationX + 30, buttonSizeHeight + buttonLocationY + 30, 600, 170);
		this.add(udpbit,new Integer(2),1);
		
		ipbit = new IP4bit();
		ipbit.setBounds(buttonLocationX + 30, buttonSizeHeight + buttonLocationY + 30, 600, 170);
		this.add(ipbit,new Integer(2),0);
		
		ebit = new Ethernetbit();
		ebit.setBounds(buttonLocationX + 30, buttonSizeHeight + buttonLocationY + 30, 600, 170);
		this.add(ebit,new Integer(2),0);
		
	}
	
	public void bitDetailDisable(){
		udpbit.setVisible(false);
		ebit.setVisible(false);
		ipbit.setVisible(false);
	}
	
	public PacketDetails(){
		
		buttonLocationX = 2;
		buttonLocationY = 2;
		
		buttonSizeWidth = 160;
		buttonSizeHeight = 40;
		
		layerButtons = new ArrayList<JButton>();
		

		
		jspPacket = new JScrollPane();
		jlPacket = new JLabel();
		
		int fontPoints = 14; // or whatever works best
	
		jlPacket.setFont(new Font(Font.MONOSPACED, Font.PLAIN, fontPoints ));
		jlPacket.setOpaque(true);
		jlPacket.setVerticalAlignment(SwingConstants.TOP);
		jlPacket.setHorizontalAlignment(SwingConstants.CENTER);
		jlPacket.setForeground(Color.white);
		jlPacket.setBackground(Color.DARK_GRAY);
		
		jspPacket.setBorder(BorderFactory.createMatteBorder(5, 5, 0, 5, Color.DARK_GRAY));
		jspPacket.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		jspPacket.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		
		
		analyzers = JDPacketAnalyzerLoader.getAnalyzers();
		
		this.setLayout(null);
		
		jspPacket.getViewport().add(jlPacket);
		
		jspPacket.setBounds(690, 0, 332, 370);
		
	}

}
